##############################################################################################
#  Copyright (C) 2007 [F.G. Hattingh]																			#
#																															#
#	 This program is free software; you can redistribute it and/or modify							
#	it under the terms of the GNU General Public License as published by								
#	the Free Software Foundation; either version 3 of the License, or									
#	(at your option) any later version.																			#	
#																															#
#	This program is distributed in the hope that it will be useful,											
#	but WITHOUT ANY WARRANTY; without even the implied warranty of										
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the										
#	GNU General Public License for more details.																#
#																															#
#	You should have received a copy of the GNU General Public License										
#	along with this program; if not, write to the Free Software											
#	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA						
#																															#
#	Contact me at: hattinghfg@tut.ac.za																	#
#																															#
# This lib will help you write applications that work with the MXIT protocoll							
# Encrypt.pm does all the encryption and decryption based on the CID from the .jad				
# It relies on:																										#	
# -Crypt::Rijndael;																									#
# -MIME::Base64;																										#
##############################################################################################

use strict;
use Crypt::Rijndael;
use MIME::Base64;

package Encrypt;

#######################
# THE CONSTRUCTOR     #
#######################

sub new 
{
my $class = shift;
my %parm = @_;
my $self  = {};
$self->{PIN} = $parm{'Pin'}; #The users unencrypted pin 
$self->{CID} = $parm{'Cid'}; #The client ID you get with the mxit jad
bless ($self, $class);
return $self;
}

sub cid
{
my $self = shift;
	if (@_) 
	{
	 $self->{CID} = shift ;
	}
	return $self->{CID};
}

sub pin
{
my $self = shift;
	if (@_) 
	{
	 $self->{PIN} = shift ;
	}
	return $self->{PIN};
}

#Encrypts the pin for the user
sub enc_pin
{
my $self = shift;

my $pin = $self->{PIN};
my $cid = $self->{CID};

#Get the correct values
my $key = &const_key($cid);
my $pass = &pad_pass($pin);

#Do the encryption
my $cipher = Crypt::Rijndael->new( $key, Crypt::Rijndael::MODE_CBC() );
my $ciphertext = $cipher->encrypt($pass);


#Covert to base 64 and assign to $pin
$pin = MIME::Base64::encode_base64($ciphertext);

#Cid also needs to change before sending to server
$cid = cid_key($cid);

#Return the newly incrypted pin and the changed cid
return ($pin,$cid);
}


#Pads the password to make sure we end up with blocksize of 16 bytes. (Also ads the "<mxit/>")	
sub pad_pass {
my $data = shift;

$data = "<mxit/>".$data;

#Padd with /0 but only until 15 the last one needs to be all the /0 +1 
$data = $data . "\0" x ( 15 - length($data)%16 );

#Hack based ont the number of \0 added it seems the last \? must be (total \0 added) +1
my  @ar = ("\0","\1", "\2", "\3","\4","\5"); 

my $count = ($data =~ tr/\0//)+1;
my $data = $data.$ar[$count];
return $data
}

#Constructs the correct key to use for ecryption based on cid 
sub const_key
{
my $key = shift;

#Get the first hash number and convert to int
my $size = hex(substr ($key, 0, 2));

#Get the first version of the key from substring that starts at position $size+2 and load each char in array
my @key_one = split(//,(substr($key, $size+2))); 

#Get the complete key by buffering @key_one with iv
my @iv = ('6', '1', '7', '0', '3', '8', '3', '4', '5', '2', '3', '4', '3', '5', '6', '7');
for(my $i = 0; $i < $#iv+1; $i++) {
	if($key_one[$i] eq '')
	{
	push(@key_one, $iv[$i]);
	}		
}

#Just a string of @key_one now padded with @iv
my $final_key =  join('',@key_one);
return $final_key;
}


#Constructs the correct cid that needs to be sent with connection
sub cid_key
{
my $key = shift;

#Get the first hash number and convert to int
my $size = hex(substr ($key, 0, 2));

#Remove unwanted part
my $to_remove = (substr($key, $size+2));
$key =~ s/$to_remove//; 

#Remove first to chars
$key =~ s/^..//; 

return $key;
}
1;
